home *** CD-ROM | disk | FTP | other *** search
/ Eagles Nest BBS 8 / Eagles_Nest_Mac_Collection_Disc_8.TOAST / Developer Tools⁄Additions / TextPertDK#1 / MPW C Sources & Examples.image / Example1 / Example1.c < prev    next >
C/C++ Source or Header  |  1993-03-05  |  38KB  |  1,488 lines

  1. /*•———————————————————————————————————————————————————————————————————————————————————•
  2.   |
  3.   |     Example 1:
  4.   |
  5.   |  © 1992, CTA, Inc..  All rights reserved.
  6.   |    
  7.   |     This example program demonstrates the fundamental calls used in
  8.   |     incorporating TextPert OCR in your application.  This example does
  9.   |     not take advantage of all calls to the TextPert engine, but it does
  10.   |  access an important subset of the entire set of calls.
  11.   |    
  12.   |     The TextPert calls used in this example are:
  13.   |
  14.   |            IMGetInfo
  15.   |            IMGetMaxStrip
  16.   |            IMFree
  17.   |            IMLockZone
  18.   |            IMNewScale
  19.   |            IMTiff2hIM
  20.   |            IMUnlockZone
  21.   |            LTSet                to change the resolution
  22.   |            LTFree
  23.   |            PAObtainObjects
  24.   |            TPDispose
  25.   |            TPAlloc
  26.   |            TPRead
  27.   |    
  28.   •———————————————————————————————————————————————————————————————————————————————————•*/
  29.  
  30.  
  31. #include "Example1.h"
  32.  
  33. /*•————————————————————————————————————————————————•
  34.   |  Prototypes.  
  35.   •————————————————————————————————————————————————•*/
  36.  
  37. static void ToolBoxInit();
  38. static void MenuBarInit();
  39. static void HandleEvent();
  40. static void DoCommand( long menuChoice );
  41. static void HandleAppleChoice( int theItem );
  42. static void HandleFileChoice( int theItem );
  43. static void DispatchOurWindowClicks();
  44. static void InitTheTextPertEngine();
  45. static void OpenAnImage();
  46. static void AnalyzeTheImage();
  47. static void ReadTheImage();
  48. static void DisposeTheImageAndTheLayout();
  49. static void FreeTheEngine();
  50. static short ShowImageChoiceDialog();
  51. static void InputImageFromDisk();
  52. static void InputImageFromScanner();
  53. static void PurgehIM(IMHandle *thehIM);
  54. static void ShowMainWindow();
  55. static Boolean ShowStartDialog();
  56. static void AboutDialog();
  57. static void InformAlert( Str255 myString );
  58. static void ErrorAlert( Str255 myString );
  59. static void EngineError();
  60. static void HearSnd();
  61.  
  62.  
  63. /*•————————————————————————————————————————————————•
  64.   |  These variables are typical for what you will
  65.   |  need when working with the TextPert engine.  
  66.   •————————————————————————————————————————————————•*/
  67.  
  68. TPHandle    hTP = 0L;
  69. IMHandle    hIM = 0L;
  70. LOHandle    hLO = 0L;
  71. TPTextOut    *TextOutBufferPtr = 0L;
  72.  
  73.  
  74. /*•————————————————————————————————————————————————•
  75.   |  These are global variables that are used by
  76.   |  this example.  Some are initialized with
  77.   |  default values
  78.   •————————————————————————————————————————————————•*/
  79.  
  80. Boolean            gDone = false,gShowStart = true;
  81. short            gStartUpVolume = 0,
  82.                 gBrightness = 6,
  83.                 gContrast = 4,
  84.                 gResolution = 300;
  85. MenuHandle        gMyMenus[2];
  86. EventRecord        gTheEvent;
  87. WindowPtr        gMyWindowPtr;
  88. Cursor            gWatchCursor;
  89. Rect            gRect[6] = {{50,176,89,479},
  90.                             {97,176,136,479},
  91.                             {144,176,183,479},
  92.                             {191,176,230,479},
  93.                             {239,176,278,479},
  94.                             {286,176,325,479}};
  95.                             
  96.  
  97.  
  98.  
  99.  
  100. /*•———————————————————————————————————————————————————————————————————————————————————•
  101.   |  This is the main routine for the program.
  102.   •———————————————————————————————————————————————————————————————————————————————————•*/
  103.  
  104. main() 
  105. {
  106.     ToolBoxInit();
  107.     
  108.     MenuBarInit();
  109.  
  110.     gMyWindowPtr = GetNewDialog(402, 0L , ((WindowPtr) -1L));
  111.     
  112.     if (!gMyWindowPtr)
  113.         ErrorAlert("\pCouldn't load the main window.");
  114.  
  115.     while (!gDone) {
  116.         if (gShowStart) {
  117.             gShowStart = false;            
  118.             gDone = ShowStartDialog();
  119.             if (!gDone)
  120.                 ShowMainWindow();
  121.         }        
  122.         HandleEvent();    
  123.     }        
  124.     
  125.     DisposeDialog((DialogPtr)gMyWindowPtr);
  126. }
  127.  
  128.  
  129.  
  130.  
  131.  
  132. /*•———————————————————————————————————————————————————————————————————————————————————•
  133.   |  Initialize the ToolBox Managers.
  134.   •———————————————————————————————————————————————————————————————————————————————————•*/
  135.     
  136. static void ToolBoxInit()
  137. {
  138.     CursHandle    hCurs;
  139.  
  140.     MaxApplZone();
  141.     InitGraf( &qd.thePort );
  142.     InitFonts();
  143.     FlushEvents( everyEvent, 0 );
  144.     InitWindows();
  145.     InitMenus();
  146.     TEInit();
  147.     InitDialogs( 0L );
  148.     InitCursor();
  149.     
  150.     hCurs = GetCursor(watchCursor);    
  151.     gWatchCursor = **hCurs;
  152. }
  153.     
  154.         
  155.  
  156.  
  157.         
  158. /*•———————————————————————————————————————————————————————————————————————————————————•
  159.   |  Set up the menubar.
  160.   •———————————————————————————————————————————————————————————————————————————————————•*/
  161.  
  162. static void MenuBarInit()
  163. {
  164.     Handle    myMenuBar;
  165.     
  166.     myMenuBar = GetNewMBar( 400 );
  167.     SetMenuBar( myMenuBar );
  168.     gMyMenus[0] = GetMHandle( 400 );
  169.     AddResMenu( gMyMenus[0] , 'DRVR' );
  170.     gMyMenus[1] = GetMHandle( 401 );
  171.     
  172.     DrawMenuBar();
  173. }
  174.  
  175.  
  176.  
  177.  
  178.  
  179. /*•———————————————————————————————————————————————————————————————————————————————————•
  180.   |  Dispatch the Events.
  181.   •———————————————————————————————————————————————————————————————————————————————————•*/
  182.  
  183. static void HandleEvent()
  184. {
  185.     WindowPtr    whichWindow;
  186.     register char    theChar;
  187.     GrafPtr    savePort;
  188.  
  189.     
  190.     WaitNextEvent( everyEvent, &gTheEvent, 1000 , 0L );
  191.     
  192.     switch( gTheEvent.what )
  193.     {
  194.         case mouseDown:
  195.             switch( FindWindow( gTheEvent.where, &whichWindow) )
  196.             {
  197.                 case    inDesk:
  198.                 case    inGoAway:
  199.                         break;
  200.             
  201.                 case    inMenuBar:
  202.                         DoCommand( MenuSelect(gTheEvent.where) );
  203.                         break;
  204.             
  205.                 case     inSysWindow:
  206.                         SystemClick( &gTheEvent, whichWindow);
  207.                         break;
  208.                         
  209.                 case    inDrag:
  210.                 case    inGrow:
  211.                         break;
  212.                         
  213.                 case     inContent:
  214.                         if (whichWindow != FrontWindow())
  215.                             SelectWindow(whichWindow);
  216.                         else {
  217.                             if ((gMyWindowPtr != NULL) && 
  218.                                 (gMyWindowPtr == FrontWindow()))
  219.                                     DispatchOurWindowClicks();
  220.                         }
  221.                         break;
  222.                         
  223.                 default: ;
  224.             }
  225.         
  226.             break;
  227.             
  228.         case keyDown:
  229.         case autoKey:             
  230.             theChar = gTheEvent.message & charCodeMask;
  231.             if ((gTheEvent.modifiers & cmdKey) != 0) 
  232.                 DoCommand(MenuKey( theChar));
  233.             break;
  234.  
  235.         case activateEvt:
  236.             InvalRect(&gMyWindowPtr->portRect);
  237.             break;
  238.  
  239.         case updateEvt:
  240.          if ((gMyWindowPtr != NULL) && (((WindowPtr)gTheEvent.message) == gMyWindowPtr)) {
  241.                 GetPort(&savePort);
  242.                 SetPort(gMyWindowPtr);
  243.                 BeginUpdate(gMyWindowPtr);
  244.                 DrawDialog(gMyWindowPtr);
  245.                 EndUpdate(gMyWindowPtr);
  246.                 
  247.                 SetPort(savePort);
  248.         }
  249.  
  250.             
  251.         default:  ;
  252.         
  253.     }
  254. }
  255.  
  256.  
  257.  
  258.  
  259.  
  260. /*•———————————————————————————————————————————————————————————————————————————————————•
  261.   |  Dispatch the menus.
  262.   •———————————————————————————————————————————————————————————————————————————————————•*/
  263.  
  264. static void DoCommand( long menuChoice )
  265. {
  266.     int        theMenu;
  267.     int        theItem;
  268.     
  269.     if ( menuChoice != 0 )
  270.     {
  271.         theMenu = HiWord( menuChoice );
  272.         theItem = LoWord( menuChoice );
  273.         
  274.         switch ( theMenu )
  275.         {
  276.             case 400:
  277.                     HandleAppleChoice( theItem );
  278.                     break;
  279.             case 401:
  280.                     HandleFileChoice( theItem );
  281.                     break;                    
  282.             default: ;
  283.         }
  284.         
  285.         HiliteMenu( 0 );
  286.     }
  287.     
  288. }
  289.  
  290.  
  291.  
  292. /*•———————————————————————————————————————————————————————————————————————————————————•
  293.   |  Dispatch selections made in the Apple menu.
  294.   •———————————————————————————————————————————————————————————————————————————————————•*/
  295.  
  296. static void HandleAppleChoice( int theItem )
  297. {
  298.     Str255        accName;
  299.     int            accNumber;
  300.     
  301.     switch ( theItem ) {
  302.         case 1:    AboutDialog();
  303.                 break;
  304.                 
  305.         default:
  306.                 GetItem( gMyMenus[0], theItem, accName );
  307.                 accNumber = OpenDeskAcc( accName );
  308.                 break;            
  309.     }
  310. }
  311.  
  312.  
  313.  
  314.  
  315.  
  316. /*•———————————————————————————————————————————————————————————————————————————————————•
  317.   |  Dispatch selections made in the File menu.
  318.   •———————————————————————————————————————————————————————————————————————————————————•*/
  319.  
  320. static void HandleFileChoice( int theItem )
  321. {
  322.     OSErr    myErr = noErr;
  323.  
  324.     switch ( theItem ) {
  325.         case 1:        gDone = true;
  326.                     break;
  327.         default:    ;
  328.     }
  329. }
  330.  
  331.  
  332.  
  333.  
  334.  
  335. /*•———————————————————————————————————————————————————————————————————————————————————•
  336.   |  Dispatch the button clicks in our window to routines which call the engine.
  337.   •———————————————————————————————————————————————————————————————————————————————————•*/
  338.  
  339. static void DispatchOurWindowClicks()
  340. {
  341.     short i = 0;
  342.     Boolean    done = false;
  343.     Point    tempP;
  344.     
  345.     tempP = gTheEvent.where;
  346.     GlobalToLocal(&tempP);
  347.     
  348.     while ((i < 6) && (!done)) {
  349.         if (PtInRect(tempP,&gRect[i])) {
  350.             done = true;
  351.             InvertRect(&gRect[i]);
  352.         }
  353.         else i++;
  354.     }
  355.  
  356.     if (done) {
  357.         while (StillDown());
  358.         InvertRect(&gRect[i]);        
  359.         switch(i) {
  360.             case 0:        InitTheTextPertEngine();
  361.                         break;
  362.  
  363.             case 1:        OpenAnImage();
  364.                         break;
  365.  
  366.             case 2:        AnalyzeTheImage();
  367.                         break;
  368.  
  369.             case 3:        ReadTheImage();
  370.                         break;
  371.  
  372.             case 4:        DisposeTheImageAndTheLayout();
  373.                         break;
  374.  
  375.             case 5:        FreeTheEngine();
  376.                         break; 
  377.             
  378.             default:    ErrorAlert("\pSomething happened that wasn't supposed to!!!");
  379.                         break;
  380.         }    
  381.         DrawDialog(gMyWindowPtr);        
  382.     }
  383. }
  384.  
  385.  
  386.  
  387.  
  388.  
  389.  
  390. /*•———————————————————————————————————————————————————————————————————————————————————•
  391.   |  The following six routines are the real meat and patatoes of this example.
  392.   |  They demonstrate the essential calls that are necessary to work with the
  393.   |  TextPert OCR engine.
  394.   |
  395.   |  InitTheTextPertEngine calls TPAlloc, which should be the first call that you make
  396.   |  when working with the TextPert engine.  Effectively, TPAlloc will launch the
  397.   |  TextPert engine and initialize global variables that are necessary for the
  398.   |  engine's operation.  After this we must call TLoadLib to load the default 
  399.   |     library, and TPSet of the necessary parameters for engine's operation,
  400.   |     (the most important are the CallBacks, but in our example we don't use it.
  401.   |
  402.   |  Always remember to check the engineStatus by calling TPError after every call
  403.   |  to the engine to ensure that a noErr result is returned.
  404.   •———————————————————————————————————————————————————————————————————————————————————•*/
  405.  
  406. static void InitTheTextPertEngine()
  407. {
  408.     DialogPtr    myDialogPtr = 0L;
  409.     GrafPtr        tempGrafPtr = 0L;
  410.     short        Error=0;
  411.  
  412.  
  413.     if (!hTP) {
  414.  
  415.  
  416.         /*—————•  Show some screen feedback for the user. */
  417.         
  418.         SetCursor(&gWatchCursor);
  419.  
  420.         myDialogPtr = GetNewDialog(404, 0L , ((WindowPtr) -1L));
  421.     
  422.         if (!myDialogPtr) {
  423.             ErrorAlert("\pCouldn't load the wait dialog.");
  424.         }
  425.     
  426.         ParamText("\pNow initializing the TextPert engine...", 0L , 0L , 0L);
  427.         GetPort(&tempGrafPtr);
  428.         BringToFront(myDialogPtr);
  429.         ShowWindow(myDialogPtr);
  430.         DrawDialog(myDialogPtr);
  431.  
  432.         
  433.         /*—————•  Initialize the TextPert engine. */
  434.         
  435.         hTP = TPAlloc(true);
  436.         if ((signed long)hTP>0)
  437.             {
  438.             TPLoadLib(hTP,nil);
  439.             Error=TPError(hTP);
  440.             }
  441.         
  442.         if (((signed long)hTP<=0) || (Error!=0))
  443.             InformAlert("\pThe call to TPNew was not successful.  The engine has not been initialized.");
  444.         else {
  445.             ShowDItem(gMyWindowPtr,2);
  446.             DrawDialog(gMyWindowPtr);
  447.         }
  448.         
  449.         
  450.         /*—————•  Clean up the dialog mess and restore the original cursor and window. */
  451.  
  452.         HideWindow(myDialogPtr);
  453.         SetPort(tempGrafPtr);
  454.         DisposeDialog(myDialogPtr);
  455.         
  456.         SetCursor(&qd.arrow);
  457.     }
  458.     else {
  459.         InformAlert("\pSorry dude.  You've already initialized the engine.");
  460.     }
  461. }
  462.     
  463.     
  464.  
  465.  
  466.  
  467. /*•———————————————————————————————————————————————————————————————————————————————————•
  468.   |  OpenAnImage will display a three-button dialog for the user to determine whether
  469.   |  the image will be obtained from disk or from scanner or cancel the operation.
  470.   |  If the image is obtained from disk, the Page Analysis Module call IMTiff2hIM will
  471.   |  be called to input the TIFF image and will return an engine-generated handle to
  472.   |  the image (called an IMHandle).  If you are interested in obtaining images from a
  473.   |  scanner, the scanner routines in this example demonstrated the necessary steps
  474.   |  for scanner input.
  475.   •———————————————————————————————————————————————————————————————————————————————————•*/
  476.  
  477. static void OpenAnImage()
  478. {
  479.     short    choice = 0;
  480.     
  481.     if (hTP) {    
  482.         if (!hIM) {
  483.             choice = ShowImageChoiceDialog();
  484.             switch (choice) {
  485.                 case 1:        InputImageFromDisk();
  486.                             break;
  487.                             
  488.                 case 2:        InputImageFromScanner();
  489.                             break;
  490.                 
  491.                 default:    break;
  492.             }
  493.             
  494.             if (hIM) {
  495.                 ShowDItem(gMyWindowPtr,3);
  496.             }            
  497.         }
  498.         else {
  499.             InformAlert("\pNo can do.  Before you obtain another image you should dispose of the one you already have.");
  500.         }
  501.     }
  502.     else {
  503.         InformAlert("\pNo way man.  You can't open an image before you initialize the engine.");
  504.     }
  505. }
  506.  
  507.  
  508.  
  509.  
  510.  
  511. /*•———————————————————————————————————————————————————————————————————————————————————•
  512.   |  AnalyzeTheImage sets up the LOParams structure for the areas that are identified
  513.   |  as text in the image, and obtains a second hIM for an image that is scaled to
  514.   |  75 dpi compared to the original image.  With an hIM for a reduced image, this 
  515.   |  routine calls PAObtainObjects which automatically
  516.   |  analyzes the image and creates a layout specification that identifies the
  517.   |  text blocks in the image.
  518.   •———————————————————————————————————————————————————————————————————————————————————•*/
  519.  
  520. static void AnalyzeTheImage()
  521. {
  522.     IMHandle    redhIM = 0L;
  523.     short        resolution = 0,rowBytes = 0;
  524.     Rect        bounds;
  525.     DialogPtr    myDialogPtr = 0L;
  526.     GrafPtr        tempGrafPtr = 0L;
  527.     
  528.     
  529.     /*—————•  Before performing automatic page analysis, you must have an hTP and an hIM. */
  530.      
  531.     if ((hTP) && (hIM)) {
  532.             
  533.                 
  534.         /*—————•  Set up some screen feedback for the user. */
  535.         
  536.         SetCursor(&gWatchCursor);
  537.  
  538.         myDialogPtr = GetNewDialog(404, 0L , ((WindowPtr) -1L));
  539.  
  540.         if (!myDialogPtr)
  541.             ErrorAlert("\pCouldn't load the wait dialog.");
  542.     
  543.         ParamText("\pNow identifying the elements in the image...\nThis process may take a few minutes.", 0L , 0L , 0L);
  544.         GetPort(&tempGrafPtr);
  545.         BringToFront(myDialogPtr);
  546.         ShowWindow(myDialogPtr);
  547.         DrawDialog(myDialogPtr);
  548.  
  549.         /*—————•  Get rid of any old hLO. */
  550.         
  551.         if (hLO) {
  552.             LTFree(hLO);
  553.             hLO = 0L;
  554.             if (TPError(hTP) != noErr)
  555.                 EngineError();
  556.         }
  557.         
  558.  
  559.         /*—————•  Obtain an hIM reference to a reduced image at 75 dpi */
  560.         
  561.         redhIM = IMNewScale(hIM,75,IM_AUTO,gStartUpVolume);
  562.         
  563.         if (TPError(hTP) != noErr) {
  564.             EngineError();
  565.         }
  566.         else {
  567.             if (redhIM) {        
  568.     
  569.                 /*—————•  Have the TextPert engine analyze the page */
  570.                 
  571.                 hLO = PAObtainObjects(redhIM,0L,nil,PA_TEXT+PA_HEADLINES);
  572.             
  573.                 if (TPError(hTP) != noErr) {
  574.                     EngineError();
  575.                 }
  576.                 
  577.                 IMFree(redhIM);
  578.  
  579.                 if (TPError(hTP) != noErr) {
  580.                     EngineError();
  581.                 }                
  582.                 
  583.                 else {
  584.                     if (hLO) {
  585.     
  586.                     
  587.                         /*•———————————————————————————————————————————————————•
  588.                           |  VERY, VERY, IMPORTANT.
  589.                           |  After obtaining an hLO for the reduced image at
  590.                           |  75 dpi, you must get the resolution of your
  591.                           |  original image (NOT of the reduced image) and
  592.                           |  convert the resolution of the layout specification
  593.                           |  to the resolution of the original image.
  594.                           •———————————————————————————————————————————————————•*/
  595.                           
  596.                         IMGetInfo( hIM , &resolution , &bounds , &rowBytes );
  597.                         
  598.                         if (TPError(hTP) != noErr) {
  599.                             EngineError();
  600.                         }
  601.                         else {
  602.                             if (resolution) {
  603.                                 LTSet(hLO,LT_RESOLUTION,(long)resolution);
  604.                                 
  605.                                 if (TPError(hTP) != noErr) {
  606.                                     EngineError();
  607.                                 }
  608.                                 else
  609.                                     ShowDItem(gMyWindowPtr,4);
  610.                             }
  611.                         }                    
  612.                     }
  613.                     else
  614.                         InformAlert("\pWow.  For some reason the page analysis process didn't create a layout specification.  Oh well.");
  615.                 }
  616.             }
  617.             else
  618.                 InformAlert("\pError: The reduced image was not created.  Bummer man.");
  619.         }
  620.         
  621.         /*—————•  Clean up the dialog mess and restore the original cursor and window. */
  622.  
  623.         HideWindow(myDialogPtr);
  624.         SetPort(tempGrafPtr);
  625.         DisposeDialog(myDialogPtr);
  626.         
  627.         SetCursor(&qd.arrow);    
  628.     }
  629.     else
  630.         InformAlert("\pWrong answer.  Before the engine can analyze an image, the engine must first be initialized and there must be an image to analyze.");
  631. }
  632.  
  633.  
  634.  
  635.  
  636.  
  637. /*•———————————————————————————————————————————————————————————————————————————————————•
  638.   |  ReadTheImage accesses the central call of the TextPert engine, RDRead.  Before
  639.   |  making this call, make sure you have obtained an hTP, hIM, hLO, and have
  640.   |  created a large enough text buffer for the engine to dump the output text to.
  641.   |     Before call RDRead, you must call TPSet to indicate the buffer for the 
  642.   |     output text and the length of this buffer.
  643.   |  The ReadTheImage routine dumps the text in the buffer to a text file called
  644.   |  TP Text Found.
  645.   •———————————————————————————————————————————————————————————————————————————————————•*/
  646.  
  647. static void ReadTheImage()
  648. {
  649.     OSErr        myError = noErr;
  650.     Str255        fileName = "\pTP Text Found";
  651.     Str255        temp1,temp2,temp3;
  652.     DialogPtr    myDialogPtr = 0L;
  653.     GrafPtr        tempGrafPtr = 0L;
  654.     short         itemHit = 0;
  655.     Rect        btnRect = {105,131,125,189};
  656.     short        fRef = 0;
  657.     long        count = 0L;
  658.     long        errorCount = 0L;
  659.     short        i = 0;
  660.     float        accuracy = 0;
  661.     
  662.     
  663.     /*—————•  Make sure there is an hTP, an hIM, and an hLO. */
  664.     
  665.     if ((hTP) && (hIM) && (hLO)) {
  666.     
  667.  
  668.         /*—————•  Set up the cursor and a dialog for user feedback. */
  669.         
  670.         SetCursor(&gWatchCursor);
  671.  
  672.         myDialogPtr = GetNewDialog(404, 0L , ((WindowPtr) -1L));
  673.     
  674.         if (!myDialogPtr)
  675.             ErrorAlert("\pCouldn't load the wait dialog.");    
  676.     
  677.         ParamText("\pNow reading the text in the image...\nThis process may take a few minutes.", 0L , 0L , 0L);
  678.         GetPort(&tempGrafPtr);
  679.         BringToFront(myDialogPtr);
  680.         ShowWindow(myDialogPtr);
  681.         DrawDialog(myDialogPtr);
  682.         
  683.  
  684.         /*—————•  Create a text output buffer.  Preferably as big as possible. */
  685.         
  686.         TextOutBufferPtr = (TPTextOut *)NewPtr(30000);
  687.         
  688.         myError = MemError();
  689.         if (!myError) {
  690.             (*TextOutBufferPtr).length = 0;
  691.             
  692.             
  693.             /*—————•  Call TPRead to have the TextPert engine perform the OCR process. */
  694.     
  695.             TPSet(hTP,TP_TEXTOUT_BUFFER,(long)TextOutBufferPtr);
  696.             TPSet(hTP,TP_TEXTOUT_LENGTH,(long)29996);    /* better leave 4 bytes free (2 bytes length and 2 more) */
  697.             RDRead(hTP,hIM,hLO);
  698.     
  699.             if (TPError(hTP) != noErr)
  700.                 EngineError();
  701.             else {
  702.             
  703.     
  704.                 /*—————•  For this example, we will write the text to a text file. */
  705.                 
  706.                 ParamText("\pNow saving the text as a text file 'TP Text Found' ...", 0L , 0L , 0L);
  707.                 DrawDialog(myDialogPtr);
  708.             
  709.                 myError = FSDelete(fileName, gStartUpVolume);    
  710.                 myError = Create(fileName, gStartUpVolume, 'MPS ', 'TEXT');
  711.     
  712.                 if (myError == noErr) {
  713.                     myError =  FSOpen(fileName, gStartUpVolume, &fRef);
  714.     
  715.                     if (myError == noErr) {    
  716.                         count = (*TextOutBufferPtr).length;
  717.                         myError =  FSWrite(fRef, &count, (Ptr)&(*TextOutBufferPtr).text);
  718.                         
  719.                         if (myError != noErr)
  720.                             InformAlert("\pError occured while writing the text to the text file.");
  721.             
  722.                         myError =  FSClose(fRef);                
  723.                     }
  724.                     else
  725.                         InformAlert("\pError occured while attempting to open the text output file.");                
  726.                 }
  727.                 else 
  728.                     InformAlert("\pError occured while attempting to create the text output file.");                        
  729.             }
  730.             
  731.             /*—————•  Get the statistics */
  732.             count = (*TextOutBufferPtr).length;
  733.             errorCount = 0;
  734.             for (i=0;i<count;i++) {
  735.                 if ((*TextOutBufferPtr).text[i] == '•')
  736.                     errorCount++;
  737.             }
  738.             sprintf((char *)temp1,"Characters Read:  %ld",count);
  739.             c2pstr(temp1);
  740.             sprintf((char *)temp2,"Unidentified Characters:  %ld",errorCount);
  741.             c2pstr(temp2);
  742.             accuracy = (count - errorCount) * 100;
  743.             sprintf((char *)temp3,"Approx. Accuracy:  %.3f%%",(accuracy / count));
  744.             c2pstr(temp3);
  745.             
  746.                         
  747.             /*—————•  Free the space occuppied by the text output buffer. */
  748.             DisposPtr((Ptr)TextOutBufferPtr);
  749.         }
  750.         else
  751.             InformAlert("\pError occured while attempting to create the text out buffer.");
  752.  
  753.  
  754.         /*—————•  Clean up the dialog mess and restore the original cursor and window. */
  755.  
  756.         HideWindow(myDialogPtr);
  757.         SetPort(tempGrafPtr);
  758.         DisposeDialog(myDialogPtr);
  759.  
  760.         SetCursor(&qd.arrow);
  761.         
  762.  
  763.         /*—————•  If there were characters read, show the results dialog */
  764.         if (count)
  765.             ParamText(temp1,temp2,temp3,0L);
  766.             myDialogPtr = GetNewDialog(410, 0L , ((WindowPtr) -1L));
  767.             
  768.             if (!myDialogPtr)
  769.                 ErrorAlert("\pCouldn't load the choice dialog.");    
  770.             
  771.             
  772.             /*—————• Bring the dialog to the screen and frame the default button */
  773.             GetPort(&tempGrafPtr);
  774.             SetPort(myDialogPtr);
  775.             BringToFront(myDialogPtr);
  776.             ShowWindow(myDialogPtr);
  777.             PenNormal();
  778.             PenSize(3,3);
  779.             InsetRect(&btnRect,-4,-4);
  780.             FrameRoundRect(&btnRect,16,16);
  781.             HearSnd();
  782.         
  783.             /*—————• Wait for the reply from the user */
  784.             ModalDialog( 0L , &itemHit );
  785.         
  786.             /*—————• Hide the dialog and dispose of its mess */        
  787.             HideWindow( myDialogPtr );
  788.             SetPort(tempGrafPtr);
  789.             
  790.             DisposeDialog(myDialogPtr);        
  791.     }
  792.     else
  793.         InformAlert("\pBefore performing the OCR process, you must first initialize the engine, and then obtain an image and a layout specification.");
  794. }
  795.  
  796.  
  797.  
  798.  
  799.  
  800. /*•———————————————————————————————————————————————————————————————————————————————————•
  801.   |  DisposeTheImageAndTheLayout is responsible for disposing of the image and the
  802.   |  layout specification.  PLEASE NOTE:  disposing of an image and disposing of a
  803.   |  layout specification do not have to be done at the same time.  They are only
  804.   |  disposed simultaneously for this example program.  You could, for instance,
  805.   |  create one layout specification that is used for reading multiple images.
  806.   •———————————————————————————————————————————————————————————————————————————————————•*/
  807.  
  808. static void DisposeTheImageAndTheLayout()
  809. {
  810.     if ((hIM) || (hLO)) {
  811.         SetCursor(&gWatchCursor);
  812.         
  813.         if (hIM) {
  814.             IMFree(hIM);
  815.             hIM = 0L;
  816.             if (TPError(hTP) != noErr)
  817.                 EngineError();
  818.         }
  819.         
  820.         if (hLO) {
  821.             LTFree(hLO);
  822.             hLO = 0L;
  823.             if (TPError(hTP) != noErr)
  824.                 EngineError();
  825.         }
  826.         
  827.         HideDItem(gMyWindowPtr,3);
  828.         HideDItem(gMyWindowPtr,4);
  829.  
  830.         SetCursor(&qd.arrow);
  831.     }
  832.     else {
  833.         InformAlert("\pSorry.  Can't dispose of something that you don't already have.");
  834.     }
  835. }
  836.  
  837.  
  838.  
  839.  
  840.  
  841. /*•———————————————————————————————————————————————————————————————————————————————————•
  842.   |  FreeTheEngine is responsible for release the TextPert engine.  NEVER try
  843.   |  to check the "engineStatus" by calling TPError after a call to TPDispose.
  844.   •———————————————————————————————————————————————————————————————————————————————————•*/
  845.  
  846. static void FreeTheEngine()
  847. {
  848.     if (hTP) {
  849.         SetCursor(&gWatchCursor);
  850.         
  851.         if ((hIM) || (hLO))
  852.             DisposeTheImageAndTheLayout();
  853.             
  854.         TPDispose(hTP);
  855.         hTP = 0L;
  856.         
  857.         HideDItem(gMyWindowPtr,2);
  858.  
  859.         SetCursor(&qd.arrow);
  860.         gShowStart = true;
  861.     }
  862.     else {
  863.         InformAlert("\pWhoops.  Before you try to release the engine you might want to try initializing it first.");
  864.     }
  865. }
  866.  
  867.  
  868.  
  869.  
  870.  
  871. /*•———————————————————————————————————————————————————————————————————————————————————•
  872.   |  The ShowImageChoiceDialog routine displays a dialog that let's the user choose
  873.   |  whether to load an image from disk or from scanner or to cancel the operation.
  874.   •———————————————————————————————————————————————————————————————————————————————————•*/
  875.  
  876. static short ShowImageChoiceDialog()
  877. {
  878.     DialogPtr    myDialogPtr = 0L;
  879.     GrafPtr        tempGrafPtr = 0L;
  880.     short         itemHit;
  881.     Rect        btnRect = {53,205,73,263};
  882.     Boolean        myReturn = false;
  883.  
  884.  
  885.     myDialogPtr = GetNewDialog(403, 0L , ((WindowPtr) -1L));
  886.     
  887.     if (!myDialogPtr)
  888.         ErrorAlert("\pCouldn't load the choice dialog.");    
  889.     
  890.     
  891.     /*—————• Bring the dialog to the screen and frame the default button */
  892.     GetPort(&tempGrafPtr);
  893.     SetPort(myDialogPtr);
  894.     BringToFront(myDialogPtr);
  895.     ShowWindow(myDialogPtr);
  896.     PenNormal();
  897.     PenSize(3,3);
  898.     InsetRect(&btnRect,-4,-4);
  899.     FrameRoundRect(&btnRect,16,16);
  900.  
  901.     /*—————• Wait for the reply from the user */
  902.     ModalDialog( 0L , &itemHit );
  903.  
  904.     /*—————• Hide the dialog and dispose of its mess */        
  905.     HideWindow( myDialogPtr );
  906.     SetPort(tempGrafPtr);
  907.     
  908.     DisposeDialog(myDialogPtr);
  909.     
  910.     DrawDialog(gMyWindowPtr);
  911.         
  912.     return((short)(LoWord(itemHit)));
  913. }
  914.  
  915.  
  916.  
  917.  
  918.  
  919. /*•———————————————————————————————————————————————————————————————————————————————————•
  920.   |  The InputImageFromDisk displays the Standard File dialog box, then opens
  921.   |  the user-selected file.  The file reference number is then passed to the engine
  922.   |  in the call to IMTiff2hIM.
  923.   •———————————————————————————————————————————————————————————————————————————————————•*/
  924.  
  925. static void InputImageFromDisk()
  926. {
  927.     OSErr                myError = noErr;
  928.     short                    refNum;
  929.     SFTypeList             myTypeList;
  930.     StandardFileReply     theReply;
  931.     DialogPtr            myDialogPtr;
  932.     GrafPtr                tempGrafPtr;
  933.     
  934.     myTypeList[0] = 'TIFF';
  935.     
  936.  
  937.     /*—————•  Use the standard get file dialog box to obtain user's request. */
  938.     
  939.     StandardGetFile(0L,1,myTypeList,&theReply);
  940.  
  941.     DrawDialog(gMyWindowPtr);
  942.         
  943.  
  944.     /*—————•  See if the user made a choice or canceled. */
  945.  
  946.     if (theReply.sfGood) {
  947.     
  948.  
  949.         /*—————•  Show some screen feedback for the user. */
  950.         
  951.         SetCursor(&gWatchCursor);
  952.         
  953.         myDialogPtr = GetNewDialog(404, 0L , ((WindowPtr) -1L));
  954.     
  955.         if (!myDialogPtr) {
  956.             ErrorAlert("\pCouldn't load the wait dialog.");
  957.         }
  958.     
  959.         ParamText("\pNow loading the TIFF image...", 0L , 0L , 0L);
  960.         GetPort(&tempGrafPtr);
  961.         BringToFront(myDialogPtr);
  962.         ShowWindow(myDialogPtr);
  963.         DrawDialog(myDialogPtr);
  964.         
  965.         
  966.         /*—————•  Open the image to obtain the file reference number. */
  967.         
  968.         myError = FSpOpenDF(&theReply.sfFile,fsCurPerm, &refNum);
  969.         
  970.         if (myError == noErr) {
  971.         
  972.             
  973.             /*—————•  Just in case...Get rid of any old hIM. */
  974.             if (hIM) {
  975.                 IMFree(hIM);
  976.                 hIM = 0L;
  977.                 if (TPError(hTP) != noErr)
  978.                     EngineError();
  979.             }
  980.  
  981.             /*—————•  Call the engine to have it input the TIFF image. */
  982.             
  983.             hIM = IMTiff2hIM( hTP , refNum , IM_AUTO , gStartUpVolume );
  984.             
  985.             if (TPError(hTP) != noErr)
  986.                 EngineError();
  987.             myError = FSClose(refNum);
  988.         }
  989.         else
  990.             InformAlert("\pAn error occured while trying to open the file containing the image.");
  991.         
  992.         /*—————•  Clean up the dialog mess and restore the original cursor and window. */
  993.  
  994.         HideWindow(myDialogPtr);
  995.         SetPort(tempGrafPtr);
  996.         DisposeDialog(myDialogPtr);
  997.                     
  998.         SetCursor(&qd.arrow);
  999.     }
  1000. }
  1001.  
  1002.  
  1003.  
  1004.  
  1005.  
  1006. /*•———————————————————————————————————————————————————————————————————————————————————•
  1007.   |
  1008.   |                                  •••  WARNING  •••
  1009.   |
  1010.   |     THIS NEXT ROUTINE IS FOR EXPERIENCED PROGRAMMERS ONLY.  NOT FOR THE WEAK AT HEART!
  1011.   |
  1012.   |  The code used within this routine contains advanced Macintosh and TextPert
  1013.   |  programming techniques.  This code has been provided to demonstrate some
  1014.   |  advanced capabilities of the TextPert engine when used in conjunction with
  1015.   |  a scanner. 
  1016.   |
  1017.   |
  1018.   |  The InputImageFromScanner routine displays a dialog which allows users to
  1019.   |  change the brightness and the contrast before scanning.  After the scan is
  1020.   |  complete, a reduced version of the image is shown in the dialog.  If the user
  1021.   |  clicks on the image, the image is magnified to display the portion of the
  1022.   |  image at the point of the click.  This routine calls the ScanImage routine which
  1023.   |  is located in the Example 1_Scan.c file.
  1024.   •———————————————————————————————————————————————————————————————————————————————————•*/
  1025.  
  1026. static void InputImageFromScanner()
  1027. {
  1028.     short        lineCount = 0,lineCountMag = 0,rRes;
  1029.     IMHandle    reducedhIM = 0L,
  1030.                 magnifiedhIM = 0L;
  1031.     Handle        tempHdl = 0L;
  1032.     DialogPtr    myDialogPtr = 0L;
  1033.     GrafPtr        tempGrafPtr = 0L;
  1034.     short         itemHit,vLines,hLines;
  1035.     Boolean        done = false,AlreadyReduced = true;
  1036.     Str255        tempStr1;
  1037.     Str255        tempStr2;
  1038.     Str255        tempStr3;
  1039.     BitMap        srcBits,srcBitsMag;
  1040.     Rect        dstRect = {15,30,315,226};
  1041.     Rect        imageOutLineRect = {13,28,317,228};
  1042.     Rect        scanRect,fromRect,toRect;
  1043.     Point        where;
  1044.     BitMap        tempBitMap;
  1045.     
  1046.  
  1047.     myDialogPtr = GetNewDialog(405, 0L , ((WindowPtr) -1L));
  1048.     
  1049.     if (!myDialogPtr)
  1050.         ErrorAlert("\pCouldn't load the scan dialog.");    
  1051.     
  1052.     
  1053.     /*—————• Bring the dialog to the screen */
  1054.     GetPort(&tempGrafPtr);
  1055.     SetPort(myDialogPtr);
  1056.     BringToFront(myDialogPtr);
  1057.     ShowWindow(myDialogPtr);
  1058.     PenNormal();
  1059.     FrameRect(&imageOutLineRect);
  1060.  
  1061.     /*—————• Wait for and process the dialog events from the user until finished */
  1062.     while (!done) {
  1063.  
  1064.         /*—————•  Make the strings for the scanner settings */
  1065.         sprintf((char *)tempStr1,"Brightness:  %hd%%",(gBrightness * 10));
  1066.         sprintf((char *)tempStr2,"Contrast:  %hd%%",(gContrast * 10));
  1067.         sprintf((char *)tempStr3,"Resolution:  %hd dpi",gResolution);        
  1068.         c2pstr(tempStr1);
  1069.         c2pstr(tempStr2);
  1070.         c2pstr(tempStr3);    
  1071.         ParamText(tempStr1,tempStr2,tempStr3,0L);
  1072.         
  1073.         /*—————•  Update the dialog */
  1074.         DrawDialog(myDialogPtr);
  1075.         
  1076.         /*—————•  Wait for the user's response */        
  1077.         ModalDialog( 0L , &itemHit );
  1078.         switch( itemHit ) {
  1079.         
  1080.             case 2:
  1081.                 /*—————•  See if the mouse click occurred in the image area of the dialog */
  1082.                 GetMouse(&where);
  1083.                 if (!(PtInRect(where,&dstRect)))
  1084.                     break;
  1085.                     
  1086.                 /*—————•  Process this request only if there exists all sizes of the image */
  1087.                 if ((!hIM) || (!reducedhIM))
  1088.                     break;
  1089.  
  1090.                 SetCursor(&gWatchCursor);
  1091.                 EraseRect(&dstRect);
  1092.  
  1093.                 /*—————•  if true, show the magnified image, else show reduced image */
  1094.                 if (AlreadyReduced) {
  1095.                     if (TPError(hTP) != noErr)
  1096.                         EngineError();
  1097.                     
  1098.                     /*—————•  Map the mouse click to the magnified image */
  1099.                     MapPt(&where,&dstRect,&srcBitsMag.bounds);
  1100.  
  1101.                     /*—————•  Center the point to the display rectangle */
  1102.                     vLines = dstRect.bottom - dstRect.top;
  1103.                     hLines = dstRect.right - dstRect.left;
  1104.                     
  1105.                     where.v = where.v - (vLines / 2);
  1106.                     where.h = where.h - (hLines / 2);
  1107.  
  1108.                     if (where.v > (srcBitsMag.bounds.bottom - vLines))
  1109.                         where.v = srcBitsMag.bounds.bottom - vLines;
  1110.                                                 
  1111.                     if (where.v < srcBitsMag.bounds.top)
  1112.                         where.v = srcBitsMag.bounds.top;
  1113.                                             
  1114.                     if (where.h > (srcBitsMag.bounds.right - hLines))
  1115.                         where.h = srcBitsMag.bounds.right - hLines;
  1116.                                                     
  1117.                     if (where.h < srcBitsMag.bounds.left)
  1118.                         where.h = srcBitsMag.bounds.left;
  1119.                     
  1120.                     if (vLines > lineCountMag)
  1121.                         vLines = lineCountMag;                
  1122.                     
  1123.                     SetRect(&fromRect,where.h,0,where.h + hLines,vLines);
  1124.                     
  1125.                     tempBitMap = srcBitsMag;
  1126.                     
  1127.                     tempBitMap.bounds.bottom = tempBitMap.bounds.top + lineCountMag;
  1128.  
  1129.                     IMLockZone(magnifiedhIM,where.v,vLines,&tempBitMap.baseAddr);                        
  1130.                     if (TPError(hTP) != noErr)
  1131.                         EngineError();
  1132.                     
  1133.                     CopyBits(&tempBitMap,&(*((GrafPort *)myDialogPtr)).portBits,
  1134.                                 &fromRect,&toRect,srcCopy,0L);
  1135.                     
  1136.                     IMUnlockZone(magnifiedhIM);
  1137.                 }
  1138.                 else {
  1139.                     /*—————•  Show the reduced image */
  1140.                     CopyBits(&srcBits,&(*((GrafPort *)myDialogPtr)).portBits,
  1141.                                 &srcBits.bounds,&dstRect,srcCopy,0L);
  1142.                 }    
  1143.                 
  1144.                 AlreadyReduced = !AlreadyReduced;
  1145.                 SetCursor(&qd.arrow);
  1146.                 break;
  1147.                 
  1148.             case 4:
  1149.                 SetCursor(&gWatchCursor);
  1150.                 EraseRect(&dstRect);
  1151.  
  1152.                 /*—————•  Just in case...Get rid of the old hIMs. */
  1153.                 if (tempHdl = IMGetHdl(hIM))
  1154.                     DisposHandle(tempHdl);
  1155.                 PurgehIM(&hIM);
  1156.                 PurgehIM(&reducedhIM);
  1157.                 PurgehIM(&magnifiedhIM);
  1158.  
  1159.                 /*—————•  Set up the 8.5" x 12" rectangular area for the scan. */                
  1160.                 SetRect(&scanRect,0,0,((gResolution * 8) + (gResolution/2)),(gResolution * 12));                
  1161.                 
  1162.                 /*—————•  Scan the image */                
  1163.                 hIM = ScanImage(&scanRect,gResolution,gBrightness,gContrast,gStartUpVolume);
  1164.                 
  1165.                 if (hIM) {
  1166.  
  1167.                     /*•————————————————————————————————————————————————————————————————•
  1168.                       |  For this example program, we create a scaled version
  1169.                       |  of the original scanned image:  at 12 dpi.
  1170.                       •————————————————————————————————————————————————————————————————•*/
  1171.  
  1172.                     reducedhIM = IMNewScale( hIM , 12 , IM_AUTO , gStartUpVolume );                    
  1173.                     if (TPError(hTP) != noErr)
  1174.                         EngineError();
  1175.                         
  1176.                     /*—————•  If there's a valid reduced image, copy it to the dialog */
  1177.                     if (reducedhIM) {
  1178.                         lineCount = IMGetMaxStrip(reducedhIM);
  1179.                         if (TPError(hTP) != noErr)
  1180.                             EngineError();
  1181.                         IMGetInfo(reducedhIM,&rRes,&srcBits.bounds,&srcBits.rowBytes);
  1182.                         if (TPError(hTP) != noErr)
  1183.                             EngineError();
  1184.                         if (lineCount > (srcBits.bounds.bottom - srcBits.bounds.top))
  1185.                             lineCount = srcBits.bounds.bottom - srcBits.bounds.top;
  1186.                         IMLockZone(reducedhIM,0,lineCount,&srcBits.baseAddr);
  1187.                         if (TPError(hTP) != noErr)
  1188.                             EngineError();            
  1189.                         
  1190.                         CopyBits(&srcBits,&(*((GrafPort *)myDialogPtr)).portBits,
  1191.                                     &srcBits.bounds,&dstRect,srcCopy,0L);
  1192.                     }
  1193.  
  1194.                     /*—————•  Create an actual size version of the image */
  1195.                     magnifiedhIM = IMNewScale( hIM , 72 , IM_AUTO , gStartUpVolume );
  1196.                     if (TPError(hTP) != noErr)
  1197.                         EngineError();
  1198.                         
  1199.                     /*—————•  If there's a valid image, get its info */
  1200.                     if (magnifiedhIM) {
  1201.                         lineCountMag = IMGetMaxStrip(magnifiedhIM);
  1202.                         if (TPError(hTP) != noErr)
  1203.                             EngineError();
  1204.                         IMGetInfo(magnifiedhIM,&rRes,&srcBitsMag.bounds,&srcBitsMag.rowBytes);
  1205.                         if (TPError(hTP) != noErr)
  1206.                             EngineError();
  1207.                         if (lineCountMag > (srcBitsMag.bounds.bottom - srcBitsMag.bounds.top))
  1208.                             lineCountMag = srcBitsMag.bounds.bottom - srcBitsMag.bounds.top;
  1209.                         toRect = dstRect;
  1210.                         if (lineCountMag < (toRect.bottom - toRect.top))
  1211.                             toRect.bottom = toRect.top + lineCountMag;
  1212.                     }
  1213.                 }
  1214.                 
  1215.                 AlreadyReduced = true;                    
  1216.                 SetCursor(&qd.arrow);
  1217.                 break;
  1218.                 
  1219.             case 5:
  1220.                 done = true;
  1221.                 break;
  1222.                 
  1223.             case 8:
  1224.                 if (gBrightness < 10)
  1225.                     gBrightness++;
  1226.                 break;
  1227.                 
  1228.             case 9:
  1229.                 if (gBrightness > 0)
  1230.                     gBrightness--;
  1231.                 break;
  1232.                 
  1233.             case 10:
  1234.                 if (gContrast < 10)
  1235.                     gContrast++;
  1236.                 break;
  1237.                 
  1238.             case 11:
  1239.                 if (gContrast > 0)
  1240.                     gContrast--;
  1241.                 break;
  1242.                 
  1243.             default:
  1244.                 break;
  1245.         }
  1246.     }
  1247.     
  1248.  
  1249.     /*—————•  Get rid of the space allocated for the reduced images */
  1250.     PurgehIM(&reducedhIM);
  1251.     PurgehIM(&magnifiedhIM);    
  1252.  
  1253.  
  1254.     /*—————• Hide the dialog and dispose of its mess */        
  1255.     HideWindow( myDialogPtr );
  1256.     SetPort(tempGrafPtr);    
  1257.     DisposeDialog(myDialogPtr);
  1258. }
  1259.  
  1260.  
  1261.  
  1262.  
  1263.  
  1264. /*•———————————————————————————————————————————————————————————————————————————————————•
  1265.   |  The PurgehIM is a minor utility routine that calls the TextPert routine
  1266.   |  which deallocates the space allocated for an image.
  1267.   •———————————————————————————————————————————————————————————————————————————————————•*/
  1268.  
  1269. static void PurgehIM(IMHandle *thehIM)
  1270. {
  1271.     if (*thehIM) {
  1272.         IMUnlockZone(*thehIM);
  1273.         if (TPError(hTP) != noErr)
  1274.             EngineError();
  1275.         IMFree(*thehIM);
  1276.         *thehIM = 0L;
  1277.         if (TPError(hTP) != noErr)
  1278.             EngineError();
  1279.     }
  1280. }            
  1281.  
  1282.  
  1283.  
  1284.  
  1285.  
  1286.  
  1287. /*•———————————————————————————————————————————————————————————————————————————————————•
  1288.   |  The ShowMainWindow routine displays the selection menu.
  1289.   •———————————————————————————————————————————————————————————————————————————————————•*/
  1290.  
  1291. static void ShowMainWindow()
  1292. {
  1293.     int            i;
  1294.  
  1295.     /*•——————————————————————————————•
  1296.       |  Preset the check boxes.
  1297.       •——————————————————————————————•*/
  1298.     
  1299.     for (i=2;i<5;i++) 
  1300.         HideDItem(gMyWindowPtr,i);    
  1301.  
  1302.     BringToFront(gMyWindowPtr);
  1303.     ShowWindow(gMyWindowPtr);
  1304.     SetPort(gMyWindowPtr);
  1305.     DrawDialog(gMyWindowPtr);
  1306. }
  1307.     
  1308.     
  1309.  
  1310.  
  1311.  
  1312.  
  1313.  
  1314. /*•———————————————————————————————————————————————————————————————————————————————————•
  1315.   |  The ShowStartDialog routine was merely added for marketing sex appeal.
  1316.   •———————————————————————————————————————————————————————————————————————————————————•*/
  1317.  
  1318. static Boolean ShowStartDialog()
  1319. {
  1320.     DialogPtr    myDialogPtr = 0L;
  1321.     GrafPtr        tempGrafPtr = 0L;
  1322.     short         itemHit;
  1323.     Rect        btnRect = {314,99,335,195};
  1324.     Boolean        myReturn = false;
  1325.  
  1326.  
  1327.     myDialogPtr = GetNewDialog(400, 0L , ((WindowPtr) -1L));
  1328.     
  1329.     if (!myDialogPtr)
  1330.         ErrorAlert("\pCouldn't load the startup dialog.");    
  1331.     
  1332.     
  1333.     /*—————• Bring the dialog to the screen and frame the default button */
  1334.     GetPort(&tempGrafPtr);
  1335.     SetPort(myDialogPtr);
  1336.     BringToFront(myDialogPtr);
  1337.     ShowWindow(myDialogPtr);
  1338.     PenNormal();
  1339.     PenSize(3,3);
  1340.     InsetRect(&btnRect,-4,-4);
  1341.     FrameRoundRect(&btnRect,16,16);
  1342.  
  1343.     /*—————• Wait for the reply from the user */
  1344.     ModalDialog( 0L , &itemHit );
  1345.     switch( itemHit ) {
  1346.         case 1:
  1347.             myReturn = false;
  1348.             break;
  1349.         case 2:
  1350.             myReturn = true;
  1351.             break;
  1352.         default:
  1353.             break;
  1354.     }
  1355.  
  1356.     /*—————• Hide the dialog and dispose of its mess */        
  1357.     HideWindow( myDialogPtr );
  1358.     SetPort(tempGrafPtr);
  1359.     
  1360.     DisposeDialog(myDialogPtr);
  1361.     
  1362.     return(myReturn);
  1363. }
  1364.     
  1365.  
  1366.  
  1367.  
  1368.  
  1369. /*•———————————————————————————————————————————————————————————————————————————————————•
  1370.   |  The AboutDialog routine displays the "About..." dialog.  Not needed for OCR!!!
  1371.   •———————————————————————————————————————————————————————————————————————————————————•*/
  1372.  
  1373. static void AboutDialog()
  1374. {
  1375.     DialogPtr    myDialogPtr = 0L;
  1376.     GrafPtr        tempGrafPtr = 0L;
  1377.     short         itemHit;
  1378.     Rect        btnRect = {266,298,286,356};
  1379.  
  1380.  
  1381.     myDialogPtr = GetNewDialog(401, 0L , ((WindowPtr) -1L));
  1382.     
  1383.     if (!myDialogPtr)
  1384.         ErrorAlert("\pCouldn't load the About dialog.");    
  1385.     
  1386.     
  1387.     /*—————• Bring the dialog to the screen and frame the default button */
  1388.     GetPort(&tempGrafPtr);
  1389.     SetPort(myDialogPtr);
  1390.     BringToFront(myDialogPtr);
  1391.     ShowWindow(myDialogPtr);
  1392.     PenNormal();
  1393.     PenSize(3,3);
  1394.     InsetRect(&btnRect,-4,-4);
  1395.     FrameRoundRect(&btnRect,16,16);
  1396.  
  1397.     /*—————• Wait for the reply from the user */
  1398.     ModalDialog( 0L , &itemHit );
  1399.  
  1400.     /*—————• Hide the dialog and dispose of its mess */        
  1401.     HideWindow( myDialogPtr );
  1402.     SetPort(tempGrafPtr);
  1403.     
  1404.     DisposeDialog(myDialogPtr);
  1405. }
  1406.  
  1407.  
  1408.  
  1409.  
  1410.  
  1411. /*•———————————————————————————————————————————————————————————————————————————————————•
  1412.   |  The InformAlert routine is used as a central dispatch to display various
  1413.   |  messages that occur during the execution of the code.
  1414.   •———————————————————————————————————————————————————————————————————————————————————•*/
  1415.  
  1416. static void InformAlert( Str255 myString )
  1417. {
  1418.     SetCursor(&qd.arrow);
  1419.  
  1420.     ParamText( myString, 0L , 0L , 0L );
  1421.     
  1422.     NoteAlert(-16411 , 0L );
  1423. }
  1424.  
  1425.  
  1426.  
  1427.  
  1428.  
  1429. /*•———————————————————————————————————————————————————————————————————————————————————•
  1430.   |  The ErrorAlert routine is used as a central dispatch to display the results of
  1431.   |  error conditions that occur during the execution of the code.  These are for
  1432.   |  unrecoverable errors when the program should not be permitted to continue.
  1433.   •———————————————————————————————————————————————————————————————————————————————————•*/
  1434.  
  1435. static void ErrorAlert( Str255 myString )
  1436. {
  1437.     SetCursor(&qd.arrow);
  1438.  
  1439.     ParamText( myString, 0L , 0L , 0L );
  1440.     
  1441.     StopAlert(-16411 , 0L );
  1442.     
  1443.     ExitToShell();
  1444. }
  1445.  
  1446.  
  1447.  
  1448.  
  1449. /*•———————————————————————————————————————————————————————————————————————————————————•
  1450.   |  The EngineError routine is used as a central call to display the results of
  1451.   |  engine error conditions that occur during the execution of the code.
  1452.   •———————————————————————————————————————————————————————————————————————————————————•*/
  1453.  
  1454. static void EngineError()
  1455. {
  1456.     char    temp[256];
  1457.  
  1458.     
  1459.     SetCursor(&qd.arrow);
  1460.     
  1461.     sprintf((char *)temp,"The TextPert Engine has identified an error condition.  Error: %hd",
  1462.             TPError(hTP));
  1463.             
  1464.     c2pstr(temp);
  1465.     
  1466.     ParamText( *(Str255 *)temp, 0L , 0L , 0L );
  1467.     
  1468.     CautionAlert(-16411 , 0L );
  1469. }
  1470.  
  1471.  
  1472.  
  1473.  
  1474. /*•———————————————————————————————————————————————————————————————————————————————————•
  1475.   |  Sound routine for debug and other attention getting activities.
  1476.   •———————————————————————————————————————————————————————————————————————————————————•*/
  1477.  
  1478. static void HearSnd()
  1479. {
  1480.     Handle    soundHandle = 0L;
  1481.     
  1482.     if (( soundHandle = GetResource( 'snd ', 1 )) != 0L)
  1483.         SndPlay( 0L, soundHandle, false);
  1484. }
  1485.  
  1486.  
  1487.  
  1488. /*====================================  THE END  =====================================*/